/*  GoogleLBS.java
 *  Copyright (c) kecp
 *  Build on 2010-6-21  16:01:18
 */

package LBS;

import Tool.Debugger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import org.json.me.JSONException;
import org.json.me.JSONObject;

/**
 * 谷歌位置服务，提供基站到地理位置的转换
 * @author kecp
 */
public class GoogleLBS implements LocationService {

    /**服务地址*/
    public final String requestUrl = "http://www.google.com/loc/json";
    /**保存的位置*/
    private Location locKeep = null;
    /**保存的基站信息*/
    private Cell cellKeep = null;

    /**
     * 根据基站等信息生成位置转换请求内容
     * @param cellid
     * @param mnc
     * @param mcc
     * @param lac
     * @return  请求串
     */
    private String makeRequest(String cellid, String mnc, String mcc, String lac) {
            StringBuffer request = new StringBuffer();
//            request.append("{\n");
//            request.append("  \"version\": \"1.1.0\",\n");
//            request.append("  \"host\": \"maps.google.com\",\n");
//            request.append("  \"cell_towers\": [\n");
//            request.append("    {\n");
//            request.append("       \"cell_id\":").append(cellid).append(",\n");
//            request.append("       \"location_area_code\":").append(lac).append(",\n");
//            request.append("       \"mobile_country_code\":").append(mcc).append(",\n");
//            request.append("       \"mobile_network_code\":").append(mnc).append("\n");
//            request.append("    }\n");
//            request.append("  ]\n");
//            request.append("}");
            InputStream ins = GoogleLBS.class.getResourceAsStream("/res/jsonRequest.txt");
            int ch;
            try {
                while ((ch = ins.read()) != -1) {
                    request.append((char)ch);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            return request.toString();
    }

    /**
     * 发送请求并取得响应
     * @param request 请求内容
     * @return 响应内容
     */
    private String postRequest(String request) {

        HttpConnection conn = null;
        InputStream in = null;
        OutputStream out = null;
        String responseStr = null;
        String errorStr = null;

        try {
             conn = (HttpConnection) Connector.open(requestUrl);

            // Set the request method
            conn.setRequestMethod(HttpConnection.POST);
            conn.setRequestProperty("ContentType", "application/json; charset=utf-8");
       //     conn.setRequestProperty("Content-Length", Integer.toString(request.length()));
            // Getting the output stream may flush the headers
            out = conn.openOutputStream();
            int requestLength = request.length();
            for (int i = 0; i < requestLength; ++i) {
                out.write(request.charAt(i));
            }

            // Opening the InputStream will open the connection
            // and read the HTTP headers. They are stored until
            // requested.
            in = conn.openInputStream();
            // Get the length and process the data
            StringBuffer responseBuf;
            long length = conn.getLength();
            if (length > 0) {
                responseBuf = new StringBuffer((int) length);
            } else {
                responseBuf = new StringBuffer(); // default length
            }
            int ch;
            while ((ch = in.read()) != -1) {
                responseBuf.append((char) ch);
            }
            responseStr = responseBuf.toString();
        } catch (IOException ex) {
            ex.printStackTrace();
            Debugger.addDebugInfo(ex, "http post error");
        }
        finally
        {
            if (in != null){
                try
                {
                    in.close();
                }
                catch (IOException e){
                }
            }
            if (out != null){
                try{
                    out.close();
                }
                catch (IOException e){
                }
            }
            if (conn != null) {
                try{
                    conn.close();
                }
                catch (IOException e){
                }
            }
        }
        return responseStr;
    }


    /**
     * 解析响应内容
     * @param response 响应内容
     * @return 解析到的位置
     */
    private Location parseResponse(String response) {
        Location loc = null;
         try {
            JSONObject o = new JSONObject(response);
            JSONObject pos = o.getJSONObject("location");
            loc.setLon( pos.getString("longitude"));
            loc.setLat(  pos.getString("latitude") );
            loc.setAccuracy( pos.getString("accuracy"));
   //         loc.setName(pos.optString("name"));

            } catch(JSONException e) {
            e.printStackTrace();
            Debugger.addDebugInfo(e, "exception when parse LBS response");
            return null;
        }
        return loc;
    }

    public Location getLocation(String cellid, String mnc, String mcc, String lac, int timeOut) {
        
        String request = makeRequest(cellid, mnc, mcc, lac);
        Debugger.addDebugInfo("request:\n" + request);
        String response = postRequest(request);
        Debugger.addDebugInfo("response:\n" + response);
        Location loct = parseResponse(response);

        return loct;
    }

    public Location getLocation(Cell cell) {
       return getLocation(cell.cell_id,cell.mnc,cell.mcc,cell.lac, 1000);
    }

    public Location getCurLocation() {
         //取得当前基站信息
        Cell cell = new Cell();
        cell.updateNetworkInfo();

        if( cell.isAvailable() == false )
            return null;

        //检查是否跟前一个查询的基站一致
        if( locKeep != null && cellKeep != null && cellKeep.isEquals(cell) ) {
            return locKeep; //一致则返回已查询到的位置
        }

        //查询并保存新的基站信息
        Location newLoct = getLocation( cell );
        if(newLoct != null) {
            locKeep = newLoct;
            cellKeep = cell;
        }

        return locKeep;
    }

    public Location getPrevLocation() {
        return locKeep;
    }

}
